package redis

import (
	"context"
	"fmt"
	"time"

	"pbj-server/config"
	"pbj-server/pkg/logger"

	"github.com/go-redis/redis/v8"
)

var (
	Client *redis.Client
	ctx    = context.Background()
)

// Init 初始化Redis连接
func Init() error {
	cfg := config.GetConfig()
	
	// 创建Redis客户端
	Client = redis.NewClient(&redis.Options{
		Addr:     cfg.GetRedisAddr(),
		Password: cfg.Redis.Password,
		DB:       cfg.Redis.Database,
		PoolSize: cfg.Redis.PoolSize,
	})
	
	// 测试连接
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	
	if err := Client.Ping(ctx).Err(); err != nil {
		return fmt.Errorf("Redis连接测试失败: %v", err)
	}
	
	logger.Info("Redis连接成功")
	return nil
}

// Close 关闭Redis连接
func Close() error {
	if Client != nil {
		return Client.Close()
	}
	return nil
}

// GetClient 获取Redis客户端
func GetClient() *redis.Client {
	return Client
}

// Set 设置键值对
func Set(key string, value interface{}, expiration time.Duration) error {
	return Client.Set(ctx, key, value, expiration).Err()
}

// Get 获取值
func Get(key string) (string, error) {
	return Client.Get(ctx, key).Result()
}

// Del 删除键
func Del(key string) error {
	return Client.Del(ctx, key).Err()
}

// Exists 检查键是否存在
func Exists(key string) (bool, error) {
	result, err := Client.Exists(ctx, key).Result()
	return result > 0, err
}

// Expire 设置过期时间
func Expire(key string, expiration time.Duration) error {
	return Client.Expire(ctx, key, expiration).Err()
}

// TTL 获取剩余过期时间
func TTL(key string) (time.Duration, error) {
	return Client.TTL(ctx, key).Result()
}

// Incr 递增
func Incr(key string) (int64, error) {
	return Client.Incr(ctx, key).Result()
}

// IncrBy 按指定值递增
func IncrBy(key string, value int64) (int64, error) {
	return Client.IncrBy(ctx, key, value).Result()
}

// Decr 递减
func Decr(key string) (int64, error) {
	return Client.Decr(ctx, key).Result()
}

// DecrBy 按指定值递减
func DecrBy(key string, value int64) (int64, error) {
	return Client.DecrBy(ctx, key, value).Result()
}

// HSet 设置哈希字段
func HSet(key string, field string, value interface{}) error {
	return Client.HSet(ctx, key, field, value).Err()
}

// HGet 获取哈希字段值
func HGet(key string, field string) (string, error) {
	return Client.HGet(ctx, key, field).Result()
}

// HGetAll 获取所有哈希字段
func HGetAll(key string) (map[string]string, error) {
	return Client.HGetAll(ctx, key).Result()
}

// HDel 删除哈希字段
func HDel(key string, fields ...string) error {
	return Client.HDel(ctx, key, fields...).Err()
}

// LPush 从左侧推入列表
func LPush(key string, values ...interface{}) error {
	return Client.LPush(ctx, key, values...).Err()
}

// RPush 从右侧推入列表
func RPush(key string, values ...interface{}) error {
	return Client.RPush(ctx, key, values...).Err()
}

// LPop 从左侧弹出列表元素
func LPop(key string) (string, error) {
	return Client.LPop(ctx, key).Result()
}

// RPop 从右侧弹出列表元素
func RPop(key string) (string, error) {
	return Client.RPop(ctx, key).Result()
}

// LRange 获取列表范围
func LRange(key string, start, stop int64) ([]string, error) {
	return Client.LRange(ctx, key, start, stop).Result()
}

// SAdd 添加集合元素
func SAdd(key string, members ...interface{}) error {
	return Client.SAdd(ctx, key, members...).Err()
}

// SRem 删除集合元素
func SRem(key string, members ...interface{}) error {
	return Client.SRem(ctx, key, members...).Err()
}

// SMembers 获取集合所有元素
func SMembers(key string) ([]string, error) {
	return Client.SMembers(ctx, key).Result()
}

// SIsMember 检查元素是否在集合中
func SIsMember(key string, member interface{}) (bool, error) {
	return Client.SIsMember(ctx, key, member).Result()
}

// ZAdd 添加有序集合元素
func ZAdd(key string, score float64, member interface{}) error {
	return Client.ZAdd(ctx, key, &redis.Z{Score: score, Member: member}).Err()
}

// ZRange 获取有序集合范围
func ZRange(key string, start, stop int64) ([]string, error) {
	return Client.ZRange(ctx, key, start, stop).Result()
}

// ZRangeWithScores 获取有序集合范围（带分数）
func ZRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {
	return Client.ZRangeWithScores(ctx, key, start, stop).Result()
}

// ZRem 删除有序集合元素
func ZRem(key string, members ...interface{}) error {
	return Client.ZRem(ctx, key, members...).Err()
}

// Pipeline 获取管道
func Pipeline() redis.Pipeliner {
	return Client.Pipeline()
}

// WithContext 使用指定上下文
func WithContext(ctx context.Context) *redis.Client {
	return Client.WithContext(ctx)
} 